package com.hk.core.authentication.api;

import com.hk.commons.util.Lazy;
import com.hk.commons.util.SpringContextHolder;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * @author kevin
 * @date 2018-08-01 16:58
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class SecurityContextUtils {

    private static final Lazy<SecurityContext> SECURITY_CONTEXT = new Lazy<>(() -> SpringContextHolder.getBean(SecurityContext.class), true);

    /**
     * 获取当前登陆用户信息
     *
     * @return {@link UserPrincipal}
     */
    public static UserPrincipal getPrincipal() {
        return SECURITY_CONTEXT.get().getPrincipal();
    }

    /**
     * 获取当前登陆用户信息
     *
     * @return {@link UserPrincipal}
     */
    public static <T extends UserPrincipal> T getPrincipalByType(Class<T> type) {
        return SECURITY_CONTEXT.get().getPrincipalByType(type);
    }

    /**
     * 判断当前用户是否有登陆
     *
     * @return 登陆返回 true,否则返回 false
     */
    public static boolean isAuthenticated() {
        return SECURITY_CONTEXT.getOptional()
                .map(SecurityContext::isAuthenticated)
                .orElse(false);
    }

    /**
     * 判断当前登陆用户是否有任意指定权限
     */
    public static boolean hasAnyPermission(String... permissions) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasAnyPermission(permissions))
                .orElse(false);
    }

    /**
     * 判断当前登陆用户是否有指定权限
     */
    public static boolean hasPermission(String permission) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasPermission(permission))
                .orElse(false);
    }

    /**
     * 判断当前登陆用户是否有指定角色
     */
    public static boolean hasRole(String role) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasRole(role))
                .orElse(false);
    }

    /**
     * 判断当前登陆用户是否有任意指定角色
     */
    public static boolean hasAnyRole(String... roles) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasAnyRole(roles))
                .orElse(false);
    }
}
